﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using WebUI.Util;
using WebUI.Models;
using Citi.OTFPC.PP.ProcessDashboard.ConsoleInterface.Util;
using System.IO;
using System.Timers;
using Citi.OTFPC.PP.ProcessDashboard.S.Console.Util;

namespace Citi.OTFPC.PP.ProcessDashboard.ConsoleInterface
{
    public class Program
    {
        public static int StartHour = int.Parse(ConfigurationManager.AppSettings["StartHour"]);
        public static int FinishHour = int.Parse(ConfigurationManager.AppSettings["FinishHour"]);
        public static int LoopingMinutes = int.Parse(ConfigurationManager.AppSettings["LoopingMinutes"]);

        static void Main(string[] args)
        {
            var emailHelper = new EmailHelper();

            Console.WriteLine();
            Console.WriteLine("Starting");

            while (true)
            {
                try
                {
                    VerifyFile();
                }
                catch
                {

                }
                finally
                {
                    Console.WriteLine(string.Format("Finished at {0}. Sleeping for {1} minutes", DateTime.Now, LoopingMinutes));
                    System.Threading.Thread.Sleep(LoopingMinutes * 60000);
                }
                //if (DateTime.Now.Hour >= StartHour && DateTime.Now.Hour <= FinishHour)
                //{
                //    VerifyFile();
                //    Console.WriteLine(string.Format("Finished at {0}. Sleeping for {1} minutes", DateTime.Now, LoopingMinutes));
                //    System.Threading.Thread.Sleep(LoopingMinutes * 60000);
                //}
                //else
                //{
                //    var nextExecution = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, StartHour, 0, 0);

                //    if (DateTime.Now.Hour > FinishHour)
                //        nextExecution.AddDays(1);

                //    var timeOut = (nextExecution - DateTime.Now);

                //    Console.WriteLine();
                //    Console.WriteLine();
                //    Console.WriteLine(string.Format("Out of time. Sleeping until {0} A.M.", StartHour));

                //    System.Threading.Thread.Sleep(timeOut);
                //}
            }
        }

        private static void VerifyFile()
        {
            try
            {
                Console.WriteLine("Reading Process File");
                Console.WriteLine();

                var xmlPath = ConfigurationManager.AppSettings["XmlPath"];

                var processFile = XmlHelper.DeserializeFromXml<WebUI.Models.ProcessFile>(xmlPath);
                var models = new List<MappingFileModel>();

                processFile.Processes = processFile.Processes.ToList();

                foreach (var item in processFile.Processes)
                {
                    Console.Write(string.Concat("Reading Process ", item.ProcessName, " - ", item.SubProcessName));

                    var model = new MappingFileModel
                    {
                        Periodicy = item.Periodicy.ToString(),
                        ProcessName = item.ProcessName,
                        SubProcessName = item.SubProcessName,
                        Responsible = item.Responsible,
                        EndTime = item.EndTime
                    };

                    using (NetworkShareAccesser.Access(item.ControlFile.Substring(2, 15), @"lac", "lac_bra_ftools", "Ferrari3k10"))
                    {
                        item.OriginalControlFile = item.ControlFile;
                        item.ControlFile = FileHelper.GetNewestFile(Path.GetDirectoryName(item.ControlFile), item.Periodicy,
                                                                    Path.GetFileNameWithoutExtension(item.ControlFile),
                                                                    Path.GetExtension(item.ControlFile));

                        var existsFileControl = !string.IsNullOrEmpty(item.ControlFile) && System.IO.File.Exists(item.ControlFile);
                        var hasOutFileXml = !string.IsNullOrEmpty(item.OutFile);

                        if (hasOutFileXml && existsFileControl)
                        {
                            var outPath = FileHelper.GetNewestFileAt(Path.GetDirectoryName(item.OutFile), System.IO.File.GetLastWriteTime(item.ControlFile),
                                Path.GetFileNameWithoutExtension(item.OutFile), Path.GetExtension(item.OutFile));
                            if (outPath != null) item.OutFile = outPath;
                        }

                        var existsOutFile = hasOutFileXml && System.IO.File.Exists(item.OutFile);

                        SetStatusAndDate(hasOutFileXml, item, model, existsFileControl, existsOutFile);
                    }

                    Console.WriteLine(string.Concat("(", model.Status, ")"));

                    models.Add(model);
                }

                Console.WriteLine();
                Console.WriteLine("Creating Results XML");
                XmlHelper.SerializeToXml(models, string.Format(ConfigurationManager.AppSettings.Get("XmlPathResults").ToString(), DateTime.Today.ToString("yyyyMMdd")));

                //SendEmail(models);

            }
            catch (FileLoadException e)
            {
                Console.WriteLine(e.Message);
            }
        }
        private static void SendEmail(List<MappingFileModel> models)
        {
            var emailHelper = new EmailHelper();

            var responsibles = models.Select(x => x.Responsible).Distinct();
            var emailBody = "O(s) processos abaixo não foram executados até o momento.\n\n";

            foreach (var responsible in responsibles)
            {
                var processes = models.Where(m => m.Responsible == responsible && m.Status == Status.Waiting).ToList();

                var message = string.Empty;
                foreach (var process in processes)
                {
                    message = string.Concat(message, "\n", process.SubProcessName);
                }

                if (!string.IsNullOrEmpty(message))
                    emailHelper.SendMailToITTools(responsible, "Error", string.Concat(emailBody, message));
            }
        }

        private static void SetStatusAndDate(bool hasOutFileXml, ProcessModel item, MappingFileModel model, bool existsFileControl, bool existsOutFile)
        {
            if (!existsFileControl && !existsOutFile)
                model.Status = Status.Waiting;

            if (existsFileControl && hasOutFileXml && !existsOutFile)
                model.Status = Status.Failed;

            if (existsFileControl && hasOutFileXml && existsOutFile)
                model.Status = Status.Executed;

            if (existsFileControl && !hasOutFileXml)
                model.Status = Status.OnLate;

            var createdTime = hasOutFileXml && existsOutFile
                ? System.IO.File.GetLastWriteTime(item.OutFile) : existsFileControl
                ? System.IO.File.GetLastWriteTime(item.ControlFile) : DateTime.MinValue;

            var priorFile = FileHelper.GetPriorNewestFileAt(Path.GetDirectoryName(item.OriginalControlFile),
                Path.GetFileNameWithoutExtension(item.OriginalControlFile), Path.GetExtension(item.ControlFile));

            var newestFile = FileHelper.GetNewestFileAt(Path.GetDirectoryName(item.OriginalControlFile),
                Path.GetFileNameWithoutExtension(item.OriginalControlFile), Path.GetExtension(item.ControlFile));

            if (priorFile != null)
            {
                var priorFileDate = System.IO.File.GetLastWriteTime(model.Status == Status.Executed || model.Status == Status.OnLate
                    ? priorFile
                    : newestFile);

                model.DeadLine = priorFileDate.AddMinutes(-priorFileDate.Minute + item.EndTime.Minute).AddSeconds(-priorFileDate.Second)
                    .AddHours(-priorFileDate.Hour + item.EndTime.Hour).AddDays(item.GetDayByPeriodicity());

                if (model.DeadLine.DayOfWeek == DayOfWeek.Saturday)
                    model.DeadLine = model.DeadLine.AddDays(2);
                else if (model.DeadLine.DayOfWeek == DayOfWeek.Sunday)
                    model.DeadLine = model.DeadLine.AddDays(1);

                //if (createdTime.AddYears(-createdTime.Year + 1).AddMonths(-createdTime.Month + 1).AddDays(-createdTime.Day + 1) >
                //    item.EndTime && (existsOutFile || existsFileControl))
                //    model.Status = Status.ExecutedAfterTime;

                if (model.DeadLine < createdTime && (existsOutFile || existsFileControl))
                    model.Status = Status.OnLate;
            }
            model.ExecutedAt = createdTime;
        }
    }
}
